package org.microframework.cloud.system.service.impl;

import java.util.Date;
import java.util.UUID;

import org.microframework.base.core.datasource.annotation.Tx;
import org.springframework.stereotype.Service;

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;

import lombok.extern.slf4j.Slf4j;

/**
 * 事务示例服务
 * 演示JFinal事务注解的使用
 */
@Service
@Slf4j
public class TransactionExampleService {

    /**
     * 简单事务示例 - 创建用户并分配角色
     * 使用@Tx注解保证事务一致性
     */
    @Tx
    public boolean createUserWithRoles(String username, String password, String[] roleIds) {
        try {
            // 生成用户ID
            String userId = UUID.randomUUID().toString().replace("-", "");
            
            // 创建用户记录
            Record user = new Record();
            user.set("id", userId);
            user.set("username", username);
            user.set("password", password);
            user.set("status", 0);
            user.set("del_flag", 0);
            user.set("create_time", new Date());
            user.set("create_by", "system");
            
            // 保存用户
            Db.save("sys_user", user);
            
            // 批量分配角色
            for (String roleId : roleIds) {
                Record userRole = new Record();
                userRole.set("user_id", userId);
                userRole.set("role_id", roleId);
                Db.save("sys_user_role", userRole);
            }
            
            log.info("用户[{}]创建成功，并分配了{}个角色", username, roleIds.length);
            return true;
        } catch (Exception e) {
            log.error("创建用户失败: {}", e.getMessage(), e);
            // 异常会自动触发事务回滚
            throw new RuntimeException("创建用户失败", e);
        }
    }
    
    /**
     * 嵌套事务示例 - 更新用户并记录操作日志
     * 外层事务和内层事务一起提交或回滚
     */
    @Tx
    public boolean updateUserStatus(String userId, int status, String operator) {
        try {
            // 更新用户状态
            int affected = Db.update("UPDATE sys_user SET status = ?, update_time = ?, update_by = ? WHERE id = ?", 
                    status, new Date(), operator, userId);
            
            if (affected == 0) {
                throw new RuntimeException("用户不存在或更新失败");
            }
            
            // 记录操作日志（使用内部事务方法）
            saveOperationLog(userId, "updateStatus", "将用户状态修改为: " + status, operator);
            
            log.info("用户[{}]状态更新为{}", userId, status);
            return true;
        } catch (Exception e) {
            log.error("更新用户状态失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新用户状态失败", e);
        }
    }
    
    /**
     * 内部事务方法 - 保存操作日志
     * 由于外层已有事务，此方法会加入到外层事务中
     */
    @Tx
    public void saveOperationLog(String targetId, String operation, String content, String operator) {
        Record log = new Record();
        log.set("id", UUID.randomUUID().toString().replace("-", ""));
        log.set("target_id", targetId);
        log.set("operation", operation);
        log.set("content", content);
        log.set("operator", operator);
        log.set("operation_time", new Date());
        
        Db.save("sys_operation_log", log);
        this.log.info("操作日志已记录: {}", content);
    }
    
    /**
     * 超时控制事务示例
     * 设置事务超时时间，超时自动回滚
     */
    @Tx(timeout = 10)
    public void longRunningOperation() {
        try {
            // 第一步操作
            Db.update("UPDATE sys_config SET value = ? WHERE name = ?", 
                    "processing", "batch_job_status");
            
            // 模拟长时间处理
            log.info("开始执行长时间操作...");
            for (int i = 0; i < 5; i++) {
                // 处理批量数据
                Db.update("UPDATE sys_user SET remark = ? WHERE id IN (SELECT id FROM sys_user LIMIT ?, 100)",
                        "批量处理" + i, i * 100);
                
                log.info("处理进度: {}%", (i + 1) * 20);
                Thread.sleep(2000); // 每批次休眠2秒
            }
            
            // 更新处理状态
            Db.update("UPDATE sys_config SET value = ? WHERE name = ?", 
                    "completed", "batch_job_status");
            
            log.info("长时间操作执行完成");
        } catch (InterruptedException e) {
            log.error("操作被中断", e);
            throw new RuntimeException("操作被中断", e);
        }
    }
} 